﻿using System;
using System.Web;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Web.UI.HtmlControls;

namespace Rison.BusinessFacade.Common
{
    public sealed class FileUploader
    {
        private string _message = string.Empty;

        private string _uploadFileName = string.Empty;//用于计算文件上传后的完整物理路径

        private const string _defaultUploadPath = "file\\upload\\";

        private FileSize _sizeUnit = FileSize.KiloByte;//附件大小限制的单位，默认为K

        private string _uploadFolder = string.Empty;//指定文件要上传的文件夹
        private string _uploadedPath = string.Empty;//文件上传后在服务器的地址
        private string _uploadedFullPath = string.Empty;//文件上传后在服务器的地址
        private string _fileLength = string.Empty;//文件大小
        private int _fileByteSize = 0;//文件的字节大小
        private string _originalName = string.Empty;//文件的原名称
        private string _extension = string.Empty;//文件的扩展名
        private string _contentType = string.Empty;//文件的类型

        //上传错误时，对外返回的错误信息。
        public string Message
        {
            get { return _message; }
        }

        private void ClearMessage()
        {
            if (!string.IsNullOrEmpty(_message))
                _message = string.Empty;
        }

        public void SetSizeUnit(FileSize unit)
        {
            _sizeUnit = unit;
        }

        #region "  文件相关的属性  "
        /// <summary>
        /// 文件上传后，存储在服务器的路径。
        /// 格式：/File/Upload/...
        /// </summary>
        public string UploadedPath
        {
            get { return _uploadedPath; }
        }

        /// <summary>
        /// 文件上传后，存储在服务器的路径（文件全名）。
        /// 格式：d:\File\Upload\aaa.xls
        /// </summary>
        public string UploadedFullPath
        {
            get { return _uploadedFullPath; }
        }

        /// <summary>
        /// 文件的大小
        /// </summary>
        public string FileLength
        {
            get { return _fileLength; }
        }

        /// <summary>
        /// 文件的字节大小
        /// </summary>
        public int FileByteSize
        {
            get { return _fileByteSize; }
        }

        /// <summary>
        /// 文件的原文件名
        /// </summary>
        public string OriginalName
        {
            get { return _originalName; }
        }

        /// <summary>
        /// 文件的扩展名
        /// </summary>
        public string Extension
        {
            get { return _extension; }
        }

        /// <summary>
        /// 文件的类型。
        /// </summary>
        public string ContentType
        {
            get { return _contentType; }
        }
        #endregion


        /// <summary>
        /// 文件所要上传的文件夹路径，不包含应用程序根地址。
        /// 如：\file\upload\
        /// 或不设置该值，那么系统将使用默认路径。
        /// 每次传入，在内部使用后将被清空。
        /// </summary>
        public string FileUploadFolder
        {
            set { _uploadFolder = value; }
            get { return _uploadFolder; }
        }


        public bool Upload(HttpPostedFile postedfile)
        {
            if (ValidateBasicInfo(postedfile, 0, null))
            {
                return DoUpload(postedfile);
            }

            return false;
        }

        //参数uploadedPath：返回文件上传后保存的相对路径，如：file/upload/file.doc
        public bool Upload(HttpPostedFile postedfile, List<string> allowedExtensions)
        {
            if (ValidateBasicInfo(postedfile, 0, allowedExtensions))
            {
                return DoUpload(postedfile);
            }

            return false;
        }

        #region "  上传要验证文件大小和类型（扩展名）的附件  "
        /// <summary>
        /// 上传附件
        /// </summary>
        /// <param name="postedfile"></param>
        /// <param name="maxSize">单位K</param>
        /// <param name="allowedExtensions"></param>
        /// <returns></returns>
        public bool Upload(HttpPostedFile postedfile, int maxSize, List<string> allowedExtensions)
        {
            if (ValidateBasicInfo(postedfile, maxSize, allowedExtensions))
            {
                return DoUpload(postedfile);
            }

            return false;
        }
        #endregion


        #region "  上传需要验证尺寸大小（高宽）的图片附件  "
        /// <summary>
        /// 上传需要验证尺寸大小（高宽）的图片附件
        /// </summary>
        /// <param name="postedfile"></param>
        /// <param name="maxSize">单位K</param>
        /// <param name="allowedExtensions"></param>
        /// <param name="maxWidth">单位px</param>
        /// <param name="maxHeight"></param>
        /// <returns></returns>
        public bool UploadImage(HttpPostedFile postedfile, int maxSize, List<string> allowedExtensions, int maxWidth, int maxHeight)
        {
            if (ValidateBasicInfo(postedfile, maxSize, allowedExtensions))
                if (!ValidateImageSize(postedfile, maxWidth, maxHeight))
                    _message = "图片的尺寸（高宽）不能超过（" + maxHeight.ToString() + "×" + maxWidth.ToString() + "）！";
                else
                {
                    return DoUpload(postedfile);
                }

            return false;
        }
        #endregion


        #region "  DoUpload  "
        private bool DoUpload(HttpPostedFile postedfile)
        {
            bool uploaded = false;
            lock (typeof(FileUploader))
            {
                _uploadFileName = GetFileFullName(postedfile.FileName);

                if (!string.IsNullOrEmpty(_uploadFileName))
                {
                    try
                    {
                        postedfile.SaveAs(_uploadFileName);
                        uploaded = true;

                        _fileByteSize = postedfile.ContentLength;
                        _fileLength = TurnFileSize(Convert.ToDouble(postedfile.ContentLength));
                        _originalName = Path.GetFileName(postedfile.FileName);
                        _uploadedPath = _uploadFileName.Replace(GlobalParams.Instance.AppPhysicalPath, "/").Replace("\\", "/");
                        _uploadedFullPath = _uploadFileName;
                        _extension = Path.GetExtension(postedfile.FileName).ToLower();
                        _contentType = postedfile.ContentType;
                    }
                    catch (IOException ex)
                    {
                        _message = "上传文件错误，可能是因为没有足够的权限！错误信息：" + ex.Message;
                    }
                    catch (UnauthorizedAccessException ex)
                    {
                        _message = "上传临时文件时失败：没有权限。<br/>请与管理员联系，对存放临时文件的文件夹的操作权限进行设置！<br/>错误信息：" + ex.Message;
                    }
                }
            }
            return uploaded;
        }
        #endregion


        #region "  读取上传后文件的全名（含完整路径）  "
        private string GetFileFullName(string fileName)
        {
            StringBuilder path = new StringBuilder();
            path.Append(GlobalParams.Instance.AppPhysicalPath);

            if (!string.IsNullOrEmpty(_uploadFolder) && !string.IsNullOrEmpty(Path.GetDirectoryName(_uploadFolder)))
            {
                if (Path.GetDirectoryName(_uploadFolder).StartsWith("\\"))
                    path.Append(Path.GetDirectoryName(_uploadFolder).Substring(1));
                else
                    path.Append(Path.GetDirectoryName(_uploadFolder));

                if (!Path.GetDirectoryName(_uploadFolder).EndsWith("\\"))
                    path.Append("\\");

                //每次使用完后，随即清空该值，下次使用时需再传入
                _uploadFolder = string.Empty;
            }
            else
            {
                path.Append(_defaultUploadPath);
                path.AppendFormat("{0}\\", DateTime.Now.ToString("yyyyMMdd"));
                if (!string.IsNullOrEmpty(CurrentLoginedUser.UserId))
                    path.AppendFormat("{0}\\", CurrentLoginedUser.UserId);
            }

            if (CreateUploadFolder(path.ToString()))
            {
                path.Append(GetFileName());
                path.Append(Path.GetExtension(fileName).ToLower());
                //if (!string.IsNullOrEmpty(Path.GetFileName(UploadFileName)))
                //    path.Append(Path.GetFileName(UploadFileName));
                //else
                //    path.Append(Path.GetFileName(fileName));

                return path.ToString();
            }

            return string.Empty;
        }

        //取得上传后的文件名：用时间数字串来作为文件名，避免文件重名及中文名可能隐含的问题
        private string GetFileName()
        {
            lock (typeof(FileUploader))
            {
                DateTime time = DateTime.Now;
                return time.ToString("yyyyMMddHHmmss") + time.Millisecond.ToString("000");
            }
        }
        #endregion


        #region "  创建上传的文件夹目录  "
        private bool CreateUploadFolder(string folderPath)
        {
            try
            {
                if (!Directory.Exists(folderPath))
                    Directory.CreateDirectory(folderPath);

                return true;
            }
            catch (IOException ex)
            {
                _message = "创建上传目录错误，可能是因为没有足够的权限！错误信息：" + ex.Message;
            }
            catch (UnauthorizedAccessException ex)
            {
                _message = "创建/读取临时文件时失败：没有权限。<br/>请与管理员联系，对存放临时文件的文件夹的操作权限进行设置！<br/>错误信息：" + ex.Message;
            }

            return false;
        }
        #endregion


        #region "   验证上传文件的基础信息  "
        private bool ValidateBasicInfo(HttpPostedFile postedfile, int maxSize, List<string> allowedExtensions)
        {
            ClearMessage();

            if (postedfile == null)
                _message = "请选择要上传的文件！";
            else if (string.IsNullOrEmpty(postedfile.FileName))
                _message = "请选择要上传的文件！";
            else if (string.IsNullOrEmpty(Path.GetExtension(postedfile.FileName)))
                _message = "未知的文件类型（文件扩展名）！";
            else if (!ValidateExtension(Path.GetExtension(postedfile.FileName), allowedExtensions))
                _message = "文件类型不允许！";
            else if (maxSize > 0)
            {
                if (_sizeUnit == FileSize.MegaByte && postedfile.ContentLength / (1024 * 1024) > maxSize)
                    _message = "文件大小不能超过" + maxSize.ToString() + "M";
                else if (_sizeUnit == FileSize.KiloByte && postedfile.ContentLength / 1024 > maxSize)
                    _message = "文件大小不能超过" + maxSize.ToString() + "K";
                else if (_sizeUnit == FileSize.Byte && postedfile.ContentLength > maxSize)
                    _message = "文件大小不能超过" + maxSize.ToString() + "B";

                if (this._sizeUnit != FileSize.KiloByte)
                    this._sizeUnit = FileSize.KiloByte;//每次计算后，重新置为默认值
            }

            return string.IsNullOrEmpty(_message);
        }
        #endregion


        #region "  验证扩展名  "
        private bool ValidateExtension(string extension, List<string> allowedExtensions)
        {
            if (allowedExtensions != null && allowedExtensions.Count > 0)
                return allowedExtensions.Contains(extension.ToLower());

            return true;
        }
        #endregion


        #region "  验证图片尺寸  "
        private bool ValidateImageSize(HttpPostedFile postedfile, int maxWidth, int maxHeight)
        {
            System.Drawing.Image image = System.Drawing.Image.FromStream(postedfile.InputStream);

            bool valid = (image.PhysicalDimension.Width <= maxWidth) && (image.PhysicalDimension.Height <= maxHeight);

            image.Dispose(); image = null;

            return valid;
        }
        #endregion


        private string TurnFileSize(double filelength)
        {
            if (filelength > (1024 * 1024))
                return (filelength / (1024 * 1024)).ToString("0.00M");
            else
                return (filelength / 1024).ToString("0.00K");
        }


       

    }
}
